package com.shycloud.mido.member.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shycloud.mido.common.core.constant.CommonConstants;
import com.shycloud.mido.common.core.util.R;
import com.shycloud.mido.common.security.util.SecurityUtils;
import com.shycloud.mido.homework.api.feign.HomeworkFeignService;
import com.shycloud.mido.homework.api.vo.AtvActiveDetailDataVO;
import com.shycloud.mido.homework.api.vo.AtvActiveDetailReqVO;
import com.shycloud.mido.homework.api.vo.AtvScheduleReqVO;
import com.shycloud.mido.homework.api.vo.AtvScheduleVO;
import com.shycloud.mido.member.api.entity.AtvAttendDetail;
import com.shycloud.mido.member.api.entity.AtvMainActive;
import com.shycloud.mido.member.api.entity.AtvPlaysSimpleDate;
import com.shycloud.mido.member.api.feign.MasterFeignService;
import com.shycloud.mido.member.api.vo.AtvActionMediaReqVO;
import com.shycloud.mido.member.api.vo.AtvAttendDetailVO;
import com.shycloud.mido.member.service.*;
import com.shycloud.mido.organ.api.entity.DiaryEntity;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import springfox.documentation.annotations.ApiIgnore;


/**
 * @author bard.bai
 */
@RestController
@AllArgsConstructor
@RequestMapping("/v1/student")
@Api(tags = "挑战赛-学生和作业")
@ApiIgnore
public class AtvStudentController {

	/** 活动 */
	private AtvMainActiveService atvMainActiveService;
	/** 活动视频 */
	private AtvActionMediaService atvActionMediaService;
	/** 用户模块 service */
	private MemberServiceV2 memberService;
	/** 纠错大师开通硬件 feign */
	private MasterFeignService masterFeignService;
	/** 活动报名业务 service */
	private AtvAttendDetailService detailService;
	/** 活动类型业务 service */
	private AtvPlaysSimpleDateService playsSimpleDateService;

	private HomeworkFeignService homeworkFeignService;
	/** 缓存工具类 */
	private final RedisTemplate redisTemplate;

	@ApiOperation("活动详情")
	@GetMapping("/activeDetail")
	public R<AtvActiveDetailDataVO> activeDetail(AtvActiveDetailReqVO vo) throws Exception {

		AtvMainActive atvMainActive = atvMainActiveService.getById(vo.getId());
		vo.setBeginDatetime(atvMainActive.getBeginDatetime());
		vo.setEndDatetime(atvMainActive.getEndDatetime());
		// 活动状态判断 1未开始 2进行中 3结束
		Integer status = atvMainActiveService.queryMainActiveStatus(vo.getId());
		if (1 == status) {
			return new R(CommonConstants.FAIL, "比赛未开始无法查看", null);
		}
		//作业微服务调用
		R<AtvActiveDetailDataVO> result = homeworkFeignService.activeDetail(vo);

		return result;
	}

	@GetMapping("signInAtv")
	@ApiOperation("活动签到")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "mainActiveId", value = "活动ID", required = true, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "memberId", value = "用户ID", required = true, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "isBatch", value = "是否是批量签到(批量签到情况下[用户ID]不传)", required = true, paramType = "query", dataType = "String")
	})
	public R<Boolean> signInAtv(String mainActiveId, String memberId, String isBatch) {

		// 活动状态判断
		Integer status = atvMainActiveService.queryMainActiveStatus(mainActiveId);

		if (StringUtils.isEmpty(isBatch)) {

			AtvAttendDetail atvAttendDetail = detailService
					.getOne(new QueryWrapper<AtvAttendDetail>()
							.eq(AtvAttendDetail.COL_MAIN_ACTIVE_ID, mainActiveId)
							.eq(AtvAttendDetail.COL_MEMBER_ID, memberId));

			if (null == atvAttendDetail) {
				return new R(CommonConstants.FAIL, "该用户没报名", false);
			}
			String attendStatus = atvAttendDetail.getStatus();
			if (!StringUtils.equals("0", attendStatus)) {
				return new R(CommonConstants.FAIL, "报名才可以签到", false);
			}
			if (0 == status) {
				return new R(CommonConstants.FAIL, "活动状态获取异常", false);
			}

			//1未开始 2开启比赛 3进行中 4结束
			if (status == 1) {
				//更新状态为 - 已参加
				atvAttendDetail.setStatus("1");
			} else if (status == 2 || status == 3) {
				//进行中的活动自动给予会员权限并参加活动
				atvAttendDetail.setStatus("2");
				//送对应类型天数的权限
				AtvMainActive mainActive = atvMainActiveService.getById(mainActiveId);
				String playId = mainActive.getPlayId();
				AtvPlaysSimpleDate type = playsSimpleDateService.getById(playId);
				memberService.addVipMemberByMemberId(atvAttendDetail.getMemberId(), type.getParams() + 1);
				masterFeignService.activateByDuration(atvAttendDetail.getMemberId(), type.getParams() + 1);
			} else {
				return new R(CommonConstants.FAIL, "活动已结束", false);
			}
			atvAttendDetail.setUpdateTime(new Date());
			atvAttendDetail.setUpdateUser(SecurityUtils.getMember().getId());
			return new R(detailService.updateById(atvAttendDetail));
		}
		//批量签到
		if ("1".equals(isBatch)) {
			List<AtvAttendDetail> atvAttendDetails = detailService
					.list(new QueryWrapper<AtvAttendDetail>()
							.eq(AtvAttendDetail.COL_MAIN_ACTIVE_ID, mainActiveId));

			for (AtvAttendDetail atvAttendDetail : atvAttendDetails) {

				if (0 == status) {
					return new R(CommonConstants.FAIL, "活动状态获取异常", false);
				}
				//1未开始 2开启比赛 3进行中 4结束
				if (status == 1) {
					//更新状态为 - 已参加
					atvAttendDetail.setStatus("1");
				} else if (status == 2 || status == 3) {
					//进行中的活动自动给予会员权限并参加活动
					atvAttendDetail.setStatus("2");
					//送对应类型天数的权限
					AtvMainActive mainActive = atvMainActiveService.getById(mainActiveId);
					String playId = mainActive.getPlayId();
					AtvPlaysSimpleDate type = playsSimpleDateService.getById(playId);
					memberService.addVipMemberByMemberId(atvAttendDetail.getMemberId(), type.getParams() + 1);
					masterFeignService.activateByDuration(atvAttendDetail.getMemberId(), type.getParams() + 1);
				} else {
					return new R(CommonConstants.FAIL, "活动已结束", false);
				}
				atvAttendDetail.setUpdateTime(new Date());
				atvAttendDetail.setUpdateUser(SecurityUtils.getMember().getId());
				detailService.updateById(atvAttendDetail);
			}
			return new R(CommonConstants.SUCCESS, "success", true);
		}
		return new R(CommonConstants.FAIL, "isBatch 参数传递错误,请找姜工确认~", false);
	}

	@ApiOperation("上传视频到日记(素材路径批量：mediaUrlList)")
	@PostMapping("/syncDiary")
	public R<Boolean> syncDiary(@RequestBody AtvActionMediaReqVO vo) throws Exception {


		if (Objects.isNull(vo.getIsWorks())) {
			vo.setIsWorks(0);
		}

		LambdaQueryWrapper<AtvAttendDetail> checkWrapper =
				Wrappers.<AtvAttendDetail>lambdaQuery()
						.eq(AtvAttendDetail::getMainActiveId, vo.getMainActiveId())
						.eq(AtvAttendDetail::getMemberId, vo.getMemberId());
		List<AtvAttendDetail> detail = detailService.list(checkWrapper);
		if (CollectionUtils.isEmpty(detail)) {
			return new R<Boolean>(false, "您未参加该活动无法上传内容");
		}

		List<String> mediaUrlList = vo.getMediaUrlList();
		int uploadSize = 0;
		if (CollectionUtils.isNotEmpty(mediaUrlList)) {
			uploadSize = mediaUrlList.size();
		}

		List<AtvActionMediaReqVO> list = atvActionMediaService.listActionMedia(vo);
		if (StringUtils.equals("1", vo.getType())) {
			//日记校验 视频 当天上传1个
			if (CollectionUtils.isNotEmpty(list) && list.size() + uploadSize >= 2) {
				return new R<Boolean>(false, "每天只能传1个日记视频");
			}
		} else {
			//图片10个
			if (CollectionUtils.isNotEmpty(list) && list.size() + uploadSize >= 11) {
				return new R<Boolean>(false, "每天只能传10个日记图片");
			}
		}
		if (CollectionUtils.isNotEmpty(mediaUrlList)) {
			for (String mediaUrl : mediaUrlList) {
				DiaryEntity diary = new DiaryEntity();
				BeanUtils.copyProperties(vo, diary);
				diary.setType(Integer.valueOf(vo.getType()));
				vo.setMediaUrl(mediaUrl);
				diary.setSrc(mediaUrl);
				atvActionMediaService.syncDiary(vo, diary);
			}
		}

		return new R<Boolean>(true, "操作成功");
	}

	@GetMapping("atvSchedule")
	@ApiOperation("小程序比赛进度")
	public R atvSchedule(@Valid AtvScheduleReqVO vo) throws Exception {

		AtvMainActive atvMainActive = atvMainActiveService.getById(vo.getId());
		vo.setBeginDatetime(atvMainActive.getBeginDatetime());
		vo.setEndDatetime(atvMainActive.getEndDatetime());

		List<AtvScheduleVO> result = homeworkFeignService.atvSchedule(vo);
		return new R(result);

	}

	@GetMapping("atvScheduleDetail")
	@ApiOperation("APP比赛进度")
	public R atvScheduleDetail(@Valid AtvScheduleReqVO vo) throws Exception {

		AtvMainActive atvMainActive = atvMainActiveService.getById(vo.getId());
		vo.setBeginDatetime(atvMainActive.getBeginDatetime());
		vo.setEndDatetime(atvMainActive.getEndDatetime());

		//获取此教师下的学生列表 - 比赛进度

		String memberId = SecurityUtils.getMember().getId();
		//获取教师的学生ID列表
		List<String> studentIds = memberService.getStudentIdsByMemberId(memberId);

		vo.setStudentIds(studentIds);

		vo.setFlg("1");

		List<AtvScheduleVO> result = homeworkFeignService.atvScheduleDetail(vo);
		return new R(result);

	}

	@GetMapping("signUp")
	@ApiOperation("点击报名")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "mainActiveId", value = "活动ID", required = true, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "username", value = "用户填写的手机号（用于登录APP的账号）", required = true, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "showname", value = "琴童姓名", required = true, paramType = "query", dataType = "String"),
	})
	public R signUp(String mainActiveId, String username, String showname, String headerUrl) {

		if (StringUtils.isEmpty(headerUrl)) {
			headerUrl = "http://zebra.atv.media.joymido.com/%E5%BE%AE%E4%BF%A1%E5%9B%BE%E7%89%87_20210506112127.png";
		}

		return new R(detailService.signUp(mainActiveId, username, showname, headerUrl));
	}

	@GetMapping("dropOut")
	@ApiOperation("退赛(报名中和签到可以退，进行中无法退赛)")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "mainActiveId", value = "活动ID", required = true, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "teatcherMemberId", value = "老师ID", required = true, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "memberId", value = "用户ID(该用户报名学生，而不是老师)", required = true, paramType = "query", dataType = "String")
	})
	public R dropOut(String mainActiveId, String teatcherMemberId, String memberId) {

		if (StringUtils.isAnyBlank(mainActiveId, memberId, teatcherMemberId)) {
			return new R(CommonConstants.FAIL, "活动ID,用户ID,老师ID必填", false);
		}
		detailService.dropOut(mainActiveId, teatcherMemberId, memberId);
		return new R(true);
	}

	@GetMapping("getStudentStatus")
	@ApiOperation("查询学生报名状态")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "mainActiveId", value = "活动ID", required = true, paramType = "query", dataType = "String"),
			@ApiImplicitParam(name = "memberId", value = "用户ID", required = true, paramType = "query", dataType = "String")
	})
	public R getStudentStatus(String mainActiveId, String memberId) {

		List<AtvAttendDetail> atvAttendDetails = detailService
				.list(new QueryWrapper<AtvAttendDetail>()
						.eq(AtvAttendDetail.COL_MEMBER_ID, memberId)
						.eq(AtvAttendDetail.COL_MAIN_ACTIVE_ID, mainActiveId));

		return new R(atvAttendDetails.size() == 0 ? "-1" : atvAttendDetails.get(0).getStatus());

	}

	@GetMapping("getSignUpList")
	@ApiOperation("获取报名列表")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "current", value = "当前页", paramType = "query", dataType = "int", required = true),
			@ApiImplicitParam(name = "size", value = "每页显示条数", paramType = "query", dataType = "int", required = true),
			@ApiImplicitParam(name = "mainActiveId", value = "活动主键ID", paramType = "query", dataType = "string", required = true)
	})
	public R<IPage<AtvAttendDetailVO>> getSignUpList(Integer current, Integer size,
													 String mainActiveId) {
		return new R(detailService.getSignUpList(new Page(current, size), mainActiveId));
	}

	@ApiOperation("日记视频查询")
	@GetMapping("/queryDiary")
	public R<IPage<AtvActionMediaReqVO>> queryDiary(Long current, Long size, AtvActionMediaReqVO vo)
			throws Exception {
		/*
		 * 查询活动上传过 并且存在日记&审核通过的个人日记
		 */
		Page<AtvActionMediaReqVO> page = new Page<>(current, size);
		IPage<AtvActionMediaReqVO> result = atvActionMediaService.pageActionMedia(page, vo);
		return new R<IPage<AtvActionMediaReqVO>>(result);
	}


	@SneakyThrows
	@ApiOperation("查询作业/挑战赛 打卡 今日是否已提醒")
	@GetMapping("checkClockHomework")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "studentId", value = "学生ID", paramType = "query", dataType = "string", required = true),
			@ApiImplicitParam(name = "point", value = "功能点(clock)", paramType = "query", dataType = "string", required = true),
			@ApiImplicitParam(name = "client", value = "客户端(APP/MINI)", paramType = "query", dataType = "string", required = false)
	})
	public R checkClockHomework(String studentId, String point, String client) {

		Map<String, String> resMap = new HashMap<>(2);
		//用户_ID
		String memberId = SecurityUtils.getMember().getId();
		//当前日期
		LocalDate now = LocalDate.now();
		//查询是否已经提示过打卡
		Object o = redisTemplate.opsForValue()
				.get("clockHomework:" + now + "_" + memberId + "_" + point + "_" + client);
		if (o == null) {
			//初始值为未完成作业
			resMap.put("okHomework", "0");
			List<String> statusList = homeworkFeignService
					.getHomeWorkStatusByStu(now.toString(), studentId);
			// 完成作业
			if (statusList != null && statusList.stream().allMatch(x -> "2".equals(x))) {
				resMap.put("okHomework", "1");
			}
			resMap.put("isClock", "0");
		} else {
			resMap.put("isClock", "1");
		}
		return new R(resMap);
	}

	@ApiOperation("作业/挑战赛 打卡")
	@GetMapping("clockHomework")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "point", value = "功能点(clock)", paramType = "query", dataType = "string", required = true),
			@ApiImplicitParam(name = "client", value = "客户端(APP/MINI)", paramType = "query", dataType = "string", required = false)
	})
	public R clockHomework(String point, String client) {
		//用户_ID
		String memberId = SecurityUtils.getMember().getId();
		//当前日期
		LocalDate now = LocalDate.now();
		//查询是否已经提示过打卡
		redisTemplate.opsForValue()
				.set("clockHomework:" + now + "_" + memberId + "_" + point + "_" + client, "1", 48,
						TimeUnit.HOURS);
		return new R(true);
	}

}
